﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace Rage.Juggernaut
{
    public class CalculationOptionsJuggernaut : ICalculationOptionBase, INotifyPropertyChanged
    {
        #region Weight Adjustments
        [DefaultValue(1)]
        public int RankingMode { get { return _rankingMode; } set { if (_rankingMode != value) { _rankingMode = value; OnPropertyChanged("RankingMode"); } } }
        private int _rankingMode = 1;

        [DefaultValue(3.1f)]
        public float HitsToSurvive { get { return _hitsToSurvive; } set { if (_hitsToSurvive != value) { _hitsToSurvive = value; OnPropertyChanged("HitsToSurvive"); } } }
        private float _hitsToSurvive = 3.1f;

        [DefaultValue(3.0f)]
        public float BurstScale { get { return _burstScale; } set { if (_burstScale != value) { _burstScale = value; OnPropertyChanged("BurstScale"); } } }
        private float _burstScale = 3.0f;

        [DefaultValue(5.0f)]
        public float ThreatScale { get { return _threatScale; } set { if (_threatScale != value) { _threatScale = value; OnPropertyChanged("ThreatScale"); } } }
        private float _threatScale = 5.0f;

        [DefaultValue(1.0f)]
        public float DPSScale { get { return _dpsScale; } set { if (_dpsScale != value) { _dpsScale = value; OnPropertyChanged("DPSScale"); } } }
        private float _dpsScale = 1.0f;
        #endregion

        [DefaultValue(true)]
        public bool SE_UseDur { get { return _SE_UseDur; } set { if (_SE_UseDur != value) { _SE_UseDur = value; OnPropertyChanged("SE_UseDur"); } } }
        private bool _SE_UseDur = true;

        #region Latency
        public float Lag { get { return _lag; } set { if (_lag != value) { _lag = value; _cachedLatency = value / 1000f; OnPropertyChanged("Lag"); } } }
        private float _lag = 179f;
        public float React { get { return _react; } set { if (_react != value) { _react = value; _cachedAllowedReact = Math.Max(0f, (value - 200f) / 1000f); OnPropertyChanged("React"); } } }
        private float _react = 220f;
        [XmlIgnore]
        public float Latency { get { if (_cachedLatency < 0 && _lag > 0) { _cachedLatency = _lag / 1000f; } return _cachedLatency; } }
        private float _cachedLatency = -1000000f;
        [XmlIgnore]
        public float AllowedReact { get { if (_cachedAllowedReact < 0 && _react > 0) { _cachedAllowedReact = Math.Max(0f, (_react - 200f) / 1000f); } return _cachedAllowedReact; } }
        private float _cachedAllowedReact = -1000000f;
        [XmlIgnore]
        public float FullLatency { get { return AllowedReact + Latency; } }
        #endregion

        [XmlIgnore]
        public JuggStances Form { get { return (JuggStances)Stance; } }
        [DefaultValue((int)JuggStances.SoresuForm)]
        public int Stance { get { return _stance; } set { if (_stance != value) { _stance = value; OnPropertyChanged("Stance"); } } }
        private int _stance = (int)JuggStances.SoresuForm;

        #region Customize Rotation
        public bool ExecRotEnabled { get { return _execRotEnabled; } set { if (_execRotEnabled != value) { _execRotEnabled = value; OnPropertyChanged("ExecRotEnabled"); } } }
        private bool _execRotEnabled = false;
        /// <summary>The default and custom Rotations to be stored in the character file</summary>
        public AbilityRotationList Rotations { get { return _rotations; } set { if (_rotations != value) { _rotations = value; OnPropertyChanged("Rotations"); } } }
        private AbilityRotationList _rotations = new AbilityRotationList();
        /// <summary>The default and custom Rotations to be stored in the character file</summary>
        public AbilityRotationList RotationsOpeners { get { return _rotationsOpeners; } set { if (_rotationsOpeners != value) { _rotationsOpeners = value; OnPropertyChanged("RotationsOpeners"); } } }
        private AbilityRotationList _rotationsOpeners = new AbilityRotationList();
        /// <summary>The default and custom Rotations to be stored in the character file</summary>
        public AbilityRotationList RotationsExecutes { get { return _rotationsExecutes; } set { if (_rotationsExecutes != value) { _rotationsExecutes = value; OnPropertyChanged("RotationsExecutes"); } } }
        private AbilityRotationList _rotationsExecutes = new AbilityRotationList();
        /// <summary>The Active rotation in the Rotations list</summary>
        [DefaultValue(0)]
        public int ActiveRotationIndex { get { return _activeRotationIndex; } set { if (_activeRotationIndex != value) { _activeRotationIndex = value; OnPropertyChanged("ActiveRotationIndex"); } } }
        private int _activeRotationIndex = 0;
        /// <summary>The Active rotation in the Rotations list</summary>
        [DefaultValue(0)]
        public int ActiveRotationIndexOpeners { get { return _activeRotationIndexOpeners; } set { if (_activeRotationIndexOpeners != value) { _activeRotationIndexOpeners = value; OnPropertyChanged("ActiveRotationIndexOpeners"); } } }
        private int _activeRotationIndexOpeners = 0;
        /// <summary>The Active rotation in the Rotations list</summary>
        [DefaultValue(0)]
        public int ActiveRotationIndexExecutes { get { return _activeRotationIndexExecutes; } set { if (_activeRotationIndexExecutes != value) { _activeRotationIndexExecutes = value; OnPropertyChanged("ActiveRotationIndexExecutes"); } } }
        private int _activeRotationIndexExecutes = 0;

        [XmlIgnore]
        public AbilityRotation ActiveRotation {
            get {
                return (Rotations.Count > 0 ? Rotations[ActiveRotationIndex] : null);
            }
            set {
                if (Rotations.Count <= 0) { return; }
                Rotations[ActiveRotationIndex] = value;
            }
        }
        [XmlIgnore]
        public AbilityRotation ActiveRotationOpener
        {
            get
            {
                return (RotationsOpeners.Count > 0 ? RotationsOpeners[ActiveRotationIndexOpeners] : null);
            }
            set
            {
                if (RotationsOpeners.Count <= 0) { return; }
                RotationsOpeners[ActiveRotationIndexOpeners] = value;
            }
        }
        [XmlIgnore]
        public AbilityRotation ActiveRotationExecute
        {
            get
            {
                return (RotationsExecutes.Count > 0 ? RotationsExecutes[ActiveRotationIndexExecutes] : null);
            }
            set
            {
                if (RotationsExecutes.Count <= 0) { return; }
                RotationsExecutes[ActiveRotationIndexExecutes] = value;
            }
        }

        public AbilityRotation GetActiveRotation() { return (Rotations.Count > 0 ? Rotations[ActiveRotationIndex] : new AbilityRotation()); }
        public AbilityRotation GetActiveRotationOpener() { return (RotationsOpeners.Count > 0 ? RotationsOpeners[ActiveRotationIndexOpeners] : new AbilityRotation()); }
        public AbilityRotation GetActiveRotationExecute() { return (RotationsExecutes.Count > 0 ? RotationsExecutes[ActiveRotationIndexExecutes] : new AbilityRotation()); }
        public void RemoveActiveRotation() { if (Rotations == null) { return; } Rotations.RemoveAt(ActiveRotationIndex); ActiveRotationIndex = Math.Min(ActiveRotationIndex, Rotations.Count - 1); }
        public void RemoveActiveRotationOpeners() { if (RotationsOpeners == null) { return; } RotationsOpeners.RemoveAt(ActiveRotationIndexOpeners); ActiveRotationIndexOpeners = Math.Min(ActiveRotationIndexOpeners, RotationsOpeners.Count - 1); }
        public void RemoveActiveRotationExecutes() { if (RotationsExecutes == null) { return; } RotationsExecutes.RemoveAt(ActiveRotationIndexExecutes); ActiveRotationIndexExecutes = Math.Min(ActiveRotationIndexExecutes, RotationsExecutes.Count - 1); }
        #endregion

        #region PTR Mode
        [DefaultValue(false)]
        public bool PtrMode { get { return _ptrMode; } set { if (_ptrMode != value) { _ptrMode = value; OnPropertyChanged("PtrMode"); } } }
        private bool _ptrMode = false;
        #endregion

        #region Functions
        public string GetXml()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(CalculationOptionsJuggernaut));
            StringBuilder xml = new StringBuilder();
            StringWriter writer = new StringWriter(xml);
            serializer.Serialize(writer, this);
            return xml.ToString();
        }
        #endregion
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string property) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property)); }
        #endregion
    }
}
